package com.team.cloudsharing.service.user;

import java.util.Calendar;
import java.util.Date;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.team.cloudsharing.dao.actionlog.ActionLogDAO;
import com.team.cloudsharing.dao.actionlog.ActionLogDO;
import com.team.cloudsharing.dao.folder.FolderDAO;
import com.team.cloudsharing.dao.remember.RememberDAO;
import com.team.cloudsharing.dao.remember.RememberDO;
import com.team.cloudsharing.dao.user.UserDAO;
import com.team.cloudsharing.dao.user.UserDO;
import com.team.cloudsharing.dto.Folder;
import com.team.cloudsharing.dto.LoginResponse;
import com.team.cloudsharing.dto.User;
import com.team.cloudsharing.dto.UserChangePwd;
import com.team.cloudsharing.service.folder.FolderService;
import com.team.cloudsharing.service.mail.MailService;
import com.team.cloudsharing.ultis.Constant;
import com.team.cloudsharing.ultis.IDGenerator;
import com.team.cloudsharing.ultis.Password;

@Service("userService")
public class UserServiceImpl implements UserService {

	final static Logger logger = Logger.getLogger(UserServiceImpl.class);

	@Autowired
	UserDAO userDAO;

	@Autowired
	FolderDAO folderDAO;

	@Autowired
	MailService mailService;

	@Autowired
	RememberDAO rememberDAO;
	
	@Autowired
	ActionLogDAO actionLogDAO;

	@Autowired
	FolderService folderService;

	@Override
	public LoginResponse login(User user) {
		LoginResponse loginResponse = new LoginResponse();
		long userId = userDAO.findUserIdByUserEmailAndPassword(user.getUserEmail(), user.getPassword());
		loginResponse.setUserId(userId);
		if (userId > 0) {
			UserDO userDO = userDAO.findUserById(userId);
			loginResponse.setUserEmail(userDO.getUserEmail());
			loginResponse.setUserName(userDO.getUserName());
			loginResponse.setUserToken(userDO.getUserToken());
			loginResponse.setAvailableCapacity(userDO.getAvailableCapacity());
			loginResponse.setUsedCapacity(userDO.getUsedCapacity());
			loginResponse.setRegistrationId(userDO.getRegistrationId());
			if (user.isRemember()) {
				rememberDAO.deleteRemember(userId);
				RememberDO rememberDO = new RememberDO(user.getRememberToken(),	userDO);
				rememberDAO.insertRemember(rememberDO);
			}

			if (user.getPlatForm() != null && user.getPlatForm().equals("pc") && actionLogDAO.findActionLogByMacAddress(user.getMacAddress()) == null) {
				ActionLogDO actionLogDO = new ActionLogDO();
				actionLogDO.setMacAddress(user.getMacAddress());
				actionLogDO.setStatus(false);
				actionLogDO.setUserDO(userDO);
				actionLogDAO.insertActionLog(actionLogDO);
			}
		}
		return loginResponse;
	}
	
	@Override
	public String logout (String macAddress) {
		ActionLogDO actionLogDO = actionLogDAO.findActionLogByMacAddress(macAddress);
		if (actionLogDO != null) {
			actionLogDAO.deleteActionLog(actionLogDO);
			return Constant.LOGOUT_SUCCESS;
		}
		return Constant.LOGOUT_FAIL;
	}

	@Override
	public LoginResponse loginSocial(User user) {
		LoginResponse loginResponse = new LoginResponse();
		if (user.getPassword().equals(Constant.SECRET_KEY_SOCIAL)) {
			UserDO userDO = userDAO.findUserByUserEmail(user.getUserEmail());
			loginResponse.setUserId(userDO.getUserId());
			if (userDO.getUserId() > 0) {
				loginResponse.setUserEmail(userDO.getUserEmail());
				loginResponse.setUserName(userDO.getUserName());
				loginResponse.setUserToken(userDO.getUserToken());
				loginResponse.setAvailableCapacity(userDO
						.getAvailableCapacity());
				loginResponse.setUsedCapacity(userDO.getUsedCapacity());
			} else {
				loginResponse.setUserId(-4L);
			}
		} else {
			loginResponse.setUserId(-4L);
		}
		return loginResponse;
	}
	
	@Override
	public LoginResponse loginWithRememberToken(String rememberToken) {
		LoginResponse loginResponse = new LoginResponse();
		RememberDO rememberDO = rememberDAO.findRememberByRememberToken(rememberToken);
		if (rememberDO != null) {
			UserDO userDO = rememberDO.getUserDO();
			loginResponse.setUserId(userDO.getUserId());
			loginResponse.setUserEmail(userDO.getUserEmail());
			loginResponse.setUserName(userDO.getUserName());
			loginResponse.setUserToken(userDO.getUserToken());
			loginResponse.setAvailableCapacity(userDO.getAvailableCapacity());
			loginResponse.setUsedCapacity(userDO.getUsedCapacity());
		} else {
			loginResponse.setUserId(-4L);
		}
		return loginResponse;
	}

	@Override
	public String register(User user) {
		String statusRegister = "";
		if (checkUserEmailAlreadyExisted(user.getUserEmail())) {
			statusRegister = Constant.EMAIL_EXIST;
		} else {
			String activationCodeGenerate = Password.createPassword(IDGenerator
					.randomString(10));
			String userToken = Password.createPassword(IDGenerator
					.randomString(8));
			UserDO userDO = new UserDO(user.getUserEmail(), user.getUserName(),
					Password.createPassword(user.getPassword()), new Date(),
					userToken, activationCodeGenerate, user.isActivated(),
					user.getRegistrationId());

			long userTempId = userDAO.insertUser(userDO);
			if (userTempId > 0) {
				statusRegister = Constant.REGISTER_SUCCESS;
				mailService.sendMailActivateAccount(user.getUserEmail());
			} else {
				statusRegister = Constant.REGISTER_FAIL;
			}
		}
		return statusRegister;
	}

	@Override
	public String registerSocial(User user) {
		String statusRegister = "";
		if (checkUserEmailAlreadyExisted(user.getUserEmail())) {
			statusRegister = Constant.EMAIL_EXIST;
		} else {
			String userToken = Password.createPassword(IDGenerator
					.randomString(8));
			UserDO userDO = new UserDO(user.getUserEmail(), user.getUserName(),
					Password.createPassword(user.getPassword()), new Date(),
					userToken, null, user.isActivated(),
					user.getRegistrationId());

			long userTempId = userDAO.insertUser(userDO);
			if (userTempId > 0) {
				statusRegister = Constant.REGISTER_SUCCESS;
				Folder folder = new Folder();
				folder.setUserEmail(userDO.getUserEmail());
				folder.setFolderName(user.getUserEmail());
				folderService.createFolderROOT(folder);
			} else {
				statusRegister = Constant.REGISTER_FAIL;
			}
		}
		return statusRegister;
	}

	@Override
	public String registerConfirm(String userEmail, String activationCode) {
		String statusConfirm = "";
		UserDO userDO = userDAO.findUserByUserEmail(userEmail);
		if (userDO != null && userDO.isActivated() == false) {
			Calendar cal = Calendar.getInstance();
			cal.set(Calendar.DAY_OF_MONTH, cal.get(Calendar.DAY_OF_MONTH) - 3);
			Date now = cal.getTime();
			if (userDO.getRegDate().compareTo(now) < 0) {
				statusConfirm = Constant.EXPIRED_ACTIVATION;
			} else {
				userDO.setActivated(true);
				userDO.setActivationCode(null);
				statusConfirm = Constant.ACTIVATE_SUCCESS;
				// if activate success then create Root folder for this user
				Folder folder = new Folder();
				folder.setUserEmail(userDO.getUserEmail());
				folder.setFolderName(userEmail);
				folderService.createFolderROOT(folder);
			}
			userDAO.updateUser(userDO);
		} else {
			statusConfirm = Constant.INVALID_ACTIVATION;
		}
		return statusConfirm;
	}

	@Override
	public boolean reSendActivationLink(String userEmail) {
		boolean isEmailExisted = checkUserEmailAlreadyExisted(userEmail);
		if (isEmailExisted) {
			// Reset date reg because it is expired
			UserDO userDO = userDAO.findUserByUserEmail(userEmail);
			userDO.setRegDate(new Date());
			userDAO.updateUser(userDO);
			mailService.sendMailActivateAccount(userEmail);
		}
		return isEmailExisted;
	}

	@Override
	public String forgetPassword(String userEmail) {
		String statusCheckForgotPassword = null;
		boolean isEmailExist = checkUserEmailAlreadyExisted(userEmail);
		if (isEmailExist) {
			mailService.sendMailForgotPassword(userEmail);
			statusCheckForgotPassword = Constant.SEND_EMAIL_FORGET_SUCCESS;
		} else {
			statusCheckForgotPassword = Constant.EMAIL_NOT_EXIST;
		}
		return statusCheckForgotPassword;
	}

	@Override
	public String changePassword(UserChangePwd userChangePwd) {
		String statusChangePwd = null;
		UserDO userDO = userDAO.findUserById(userChangePwd.getUser()
				.getUserId());
		String oldPassword = userDO.getPassword();
		String newPasswordDecode = Password.createPassword(userChangePwd
				.getNewPassword());
		if (oldPassword.equals(userChangePwd.getUser().getPassword())) {
			userDO.setPassword(newPasswordDecode);
			String userToken = Password.createPassword(IDGenerator
					.randomString(8));
			userDO.setUserToken(userToken);
			long userId = userDAO.updateUser(userDO);
			statusChangePwd = (userId > 0) ? Constant.CHANGE_PASSWORD_SUCCESS
					: Constant.CHANGE_PASSWORD_FAILURE;
		} else {
			statusChangePwd = Constant.CHANGE_PASSWORD_FAILURE;
		}
		return statusChangePwd;
	}

	@Override
	public boolean checkUserEmailAlreadyExisted(String userEmail) {
		return (userDAO.findUserByUserEmail(userEmail) != null);
	}

	@Override
	public String getRememberToken(User user) {
		String rememberToken;
		UserDO userDO = userDAO.findUserByUserEmail(user.getUserEmail());
		rememberToken = rememberDAO.findRememberTokenByUserId(userDO
				.getUserId());
		return rememberToken;
	}

	@Override
	public void updateRegistrationId(User user) {
		UserDO userDO = userDAO.findUserById(user.getUserId());
		if (userDO != null) {
			userDO.setRegistrationId(user.getRegistrationId());
			userDAO.updateUser(userDO);

		}
	}

	@Override
	public Long increaseUsedCapacity(String userEmail, Long capacity) {
		UserDO userDO = userDAO.findUserByUserEmail(userEmail);
		if (userDO != null){
			Long usedCapacity = userDO.getUsedCapacity();
			Long availableCapacity = userDO.getAvailableCapacity();
			if (usedCapacity + capacity <= availableCapacity){
				userDO.setUsedCapacity(usedCapacity + capacity);
				userDAO.updateUser(userDO);
			}
		}
		userDO = userDAO.findUserByUserEmail(userEmail);
		return userDO.getUsedCapacity();
	}

	@Override
	public Long decreaseUsedCapacity(String userEmail, Long capacity) {
		UserDO userDO = userDAO.findUserByUserEmail(userEmail);
		if (userDO != null){
			Long usedCapacity = userDO.getUsedCapacity();
			if (usedCapacity - capacity >= 0){
				userDO.setUsedCapacity(usedCapacity - capacity);
				userDAO.updateUser(userDO);
			}
		}
		userDO = userDAO.findUserByUserEmail(userEmail);
		return userDO.getUsedCapacity();
	}

	@Override
	public Long getCapacity(String userEmail) {
		UserDO userDO = userDAO.findUserByUserEmail(userEmail);
		return userDO.getUsedCapacity();
	}
}
